﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
using System.Security.Cryptography;

//仅供测试使用，不对产生的任何问题负责
//作者：不正常人类研究中心首席CEO
//时间：2015.12.3
//qq：260869626
//功能：用于AES加密测试，bootloader的密钥与这里的密钥相同，更改密钥自己看着办，程序很简单，看看就懂了，作为程序猿，连这都看不懂还不如回家卖红薯了


namespace RJX_AES_ENCODE
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private FileStream  fileStream;
        private OpenFileDialog fdl;      
        private byte[]      fileData;
        //private byte[]      date;         
        private byte[]      encode_Data;                  
        private byte[]      decode_Data;
        long len = 0;
        long MOD16 = 0;
        long Bytes=0;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void 加密文件按钮_Click(object sender, RoutedEventArgs e)
        {
            程序信息.Text = null;
            openfile();
            if (fileData != null)
            {
                FileInfo fileInfo = new FileInfo(fdl.FileName);
                程序信息.Text = "文件名:   " + fileInfo.Name + "\r\n";
                程序信息.Text += "大小:     " + ((float)fileInfo.Length / 1024).ToString() + "KB, " + fileInfo.Length.ToString() + "bytes" + "\r\n";
                程序信息.Text += "路径:     " + fileInfo.DirectoryName + "\r\n";
                程序信息.Text += "创建时间: " + fileInfo.CreationTime.ToString() + "\r\n";
                程序信息.Text += "修改时间: " + fileInfo.LastWriteTime.ToString() + "\r\n";
                程序信息.Text += "访问时间: " + fileInfo.LastAccessTime.ToString() + "\r\n";
                Bytes=fileInfo.Length;

                encode_Data= AesEncryptor(fileData);//做AES加密
                程序信息.Text += "加密完成" + "\r\n";

                SaveFileDialog sdl = new SaveFileDialog();
                sdl.Title = "保存文件";
                sdl.Filter = "lhd文件|*.lhd|所有文件|*.*";
                sdl.FileName = string.Empty;
                sdl.FilterIndex = 1;
                sdl.RestoreDirectory = true;
                sdl.DefaultExt = "lhd";
                sdl.AddExtension = true;
                sdl.RestoreDirectory = true;  
                DialogResult result = sdl.ShowDialog();

                if (result == System.Windows.Forms.DialogResult.Cancel)
                {
                    return;
                }
                Stream flstr = new FileStream(sdl.FileName, FileMode.Create);
                BinaryWriter sw = new BinaryWriter(flstr, Encoding.Unicode);

                sw.Write(encode_Data);//写程序加密数据

                sw.Close();
                flstr.Close();
                fileData = null;
                encode_Data= null;
                decode_Data = null;
            }
        }

        private void openfile()
        {
            fileData = null;
            encode_Data = null;
            decode_Data = null;
            //date = null;

            fdl = new OpenFileDialog();
            fdl.Title = "选择要加密的文件";
            fdl.Filter = "bin文件|*.bin|所有文件|*.*";
            fdl.FileName = string.Empty;
            fdl.FilterIndex = 1;
            fdl.RestoreDirectory = true;
            fdl.DefaultExt = "bin";
            DialogResult result = fdl.ShowDialog();

            if (result == System.Windows.Forms.DialogResult.Cancel)
            {
                return;
            }
            else if (result == System.Windows.Forms.DialogResult.OK)
            {
                using (fileStream = File.Open(fdl.FileName, FileMode.Open))
                {
                    if (fileStream.Length <= 1024 * 1024 * 5)//文件大小限制5MB
                    {
                        if (fileStream.Length % 16 != 0)
                        {
                            len = fileStream.Length + (16 - fileStream.Length % 16);
                            MOD16 = 16 - fileStream.Length % 16;
                        }
                        else
                        {
                            len = fileStream.Length;
                            MOD16 = 0;
                        }
                        fileData = new byte[len];          //文件长度始终为16的倍数
                        encode_Data = new byte[len]; //加密后的文件长度始终为源文件长度，后面追加自定义数据
                        decode_Data = new byte[len];
                    }
                    else
                    {
                        fileStream.Close();
                        return;
                    }

                    SafeRead(fileStream, fileData);
                    fileStream.Close();
                }

            }

        }
        //安全读取文件
        private void SafeRead(Stream stream, byte[] data)
        {  
            int offset=0;        
            int remaining = data.Length;  
        
            // C#读取文件之只要有剩余的字节就不停的读         
            while (remaining > 0)
            {        
                int read = stream.Read(data, offset, remaining);

                if (read <= 0)
                {
                    //throw new EndOfStreamException("文件读取到" + read.ToString() + "失败！");
                    break;
                }
                // C#读取文件之减少剩余的字节数  
                remaining -= read;  
                // C#读取文件之增加偏移量  
                offset += read;       
       	    }   
        }


        private byte[] AesEncryptor(byte[] bsFile)
        {

            byte[] AESKEY =  System.Text.Encoding.Default.GetBytes ( "1234567890ABCDEFGHIJabcdefghiLHD" );;//这个跟boot要一致否则解不出钥匙
      
            RijndaelManaged aes = new RijndaelManaged();
            aes.KeySize = 256;
            aes.Key = AESKEY;
            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            ICryptoTransform transform = aes.CreateEncryptor();
            byte[] ENCODE_DATE= transform.TransformFinalBlock(bsFile, 0, bsFile.Length);//加密bin文件

            
            byte[] add_data = Encoding.GetEncoding("GB2312").GetBytes("LIHENG_LH988_UDFFILE");//文件头部加识别数据，这个数据根据自己需要来取，可以是公司名字什么的，底层判断这个标记正确则进行升级，否则不处理
            byte[] UNUSE_DATE = new byte[512];//头部第一包512不包含程序数据

            for (int i = 0; i < UNUSE_DATE.Length; i++)
            {
                UNUSE_DATE[i] = 0;//填充混第一包数据据包够512
            }
            for (int i = 0; i < add_data.Length; i++)
            {
                UNUSE_DATE[i] = add_data[i];//填充识别数据
            }
            
            UNUSE_DATE[32]=(byte)(Bytes>>24);
            UNUSE_DATE[33]=(byte)(Bytes>>16);
            UNUSE_DATE[34]=(byte)(Bytes>>8);
            UNUSE_DATE[35]=(byte)Bytes;


            return UNUSE_DATE.Concat(ENCODE_DATE).ToArray(); //合并两个数据输出整个加密包

        }



    }
}
